#include "lib/global.h"
#include "interrupt/interrupt.h"
#include "lib/print.h"

IntrHandle IntrSolveTable[0x80];
char* intr_name[0x80];

static void general_intr_handler(uint8_t vec_nr){
   if (vec_nr == 0x27 || vec_nr == 0x2f) {	// 0x2f是从片8259A上的最后一个irq引脚，保留
      return;		//IRQ7和IRQ15会产生伪中断(spurious interrupt),无须处理。
   }
   PutString_S("\n");
   // ######### exception message : ######### 用#凑够80个字符
   PutString_S("############################# exception message : ##############################");
   PutString_S("\n");
   char temp[100];
   FormatPrint(temp, "Exception: %d\n", vec_nr);
   PutString_S(temp);
   PutString_S("\n");
   PutString_S(intr_name[vec_nr]);
   PutString_S("\n");
   if(vec_nr == 14) {   //page fault
      int page_fault_vaddr = 0; 
      asm ("movl %%cr2, %0" : "=r" (page_fault_vaddr));	  // cr2是存放造成page_fault的地址
      FormatPrint(temp, "Page Fault(dec): %d\n", page_fault_vaddr);
      PutString_S(temp);
   }
   PutString_S("############################# exception message end ############################");
   PutString_S("\n");
   while(1);
}
void InitGeneralHandler(){
   for(int i = 0; i <= 0x80; i++){
      IntrSolveTable[i] = general_intr_handler;
      intr_name[i] = "Unknown";
   }
   intr_name[0] = "#DE Divide Error";
   intr_name[1] = "#DB Debug Exception";
   intr_name[2] = "NMI Interrupt";
   intr_name[3] = "#BP Breakpoint Exception";
   intr_name[4] = "#OF Overflow Exception";
   intr_name[5] = "#BR BOUND Range Exceeded Exception";
   intr_name[6] = "#UD Invalid Opcode Exception";
   intr_name[7] = "#NM Device Not Available Exception";
   intr_name[8] = "#DF Double Fault Exception";
   intr_name[9] = "Coprocessor Segment Overrun";
   intr_name[10] = "#TS Invalid TSS Exception";
   intr_name[11] = "#NP Segment Not Present";
   intr_name[12] = "#SS Stack Fault Exception";
   intr_name[13] = "#GP General Protection Exception";
   intr_name[14] = "#PF Page-Fault Exception";
   // intr_name[15] 第15项是intel保留项，未使用
   intr_name[16] = "#MF x87 FPU Floating-Point Error";
   intr_name[17] = "#AC Alignment Check Exception";
   intr_name[18] = "#MC Machine-Check Exception";
   intr_name[19] = "#XF SIMD Floating-Point Exception";
}
void RegisterIntrHandler(uint8_t vectorIndex, IntrHandle function){
   IntrSolveTable[vectorIndex] = function;
   InitIdt();
}
void DeleteIntrHandler(uint8_t vectorIndex){
   IntrSolveTable[vectorIndex] = NULL;
   InitIdt();
}
/* 获取当前中断状态 */
enum intrStates intr_get_status() {
   enum intrStates eflags = 0; 
   // 获取eflags寄存器的值
   asm volatile("pushfl \n popl %0" : "=g" (eflags));
   return (EFLAGS_IF & eflags) ? INTR_ON : INTR_OFF;
}
enum intrStates intr_set_status(enum intrStates state) {
   enum intrStates old_state = intr_get_status();
   if (state == INTR_ON) {
      asm volatile("sti");
   } else {
      asm volatile("cli");
   }
   return old_state;
}
enum intrStates EnableIntr(void) {
   if (INTR_ON == intr_get_status()) {
      return INTR_ON;
   } else {
      asm volatile("sti");	 // 开中断,sti指令将IF位置1
      return INTR_OFF;
   }
}
enum intrStates DisableIntr(void) {
   if (INTR_ON == intr_get_status()) {
      asm volatile("cli" : : : "memory");	 // 开中断,sti指令将IF位置1
      return INTR_ON;
   } else {
      return INTR_OFF;
   }
}
